<?php

namespace app\service;

use app\model\EntityModel;
use app\tool\SingletonTrait;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

class EntityDownstreamService
{

    use SingletonTrait;


    /**
     * @param $entity
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getDesignDownstreamEntities($entity): array
    {
        $entityJson = json_decode($entity['json'], true);
        $eq = EntityModel::where("project_id", $entity['project_id'])->where("code", $entity['code']);
        if ($entityJson['design_category'] === '关卡') {
            $eq->where("module_id", ModuleService::getInstance()->byCode('level')['id']);
        } else {
            $eq->where("module_id", ModuleService::getInstance()->byCode('asset')['id']);
        }
        $res = $eq->order('id desc')->find();
        if (empty($res)) {
            return [];
        }
        $res = [$res];
        if ($entityJson['design_category'] === '关卡') {
            $resDownstreamEntity = $this->getLevelDownstreamEntities($res);
        } else {
            $resDownstreamEntity = $this->getAssetDownstreamEntities($res);
        }
        if (!empty($resDownstreamEntity)) {
            $res = array_merge($res, $resDownstreamEntity);
        }

        return $res;
    }

    /**
     * 查询关卡的下游实体列表
     * @param $entity
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getLevelDownstreamEntities($entity): array
    {
        $entityList = EntityModel::where("project_id", $entity['project_id'])
            ->where("module_id", "IN", [ModuleService::getInstance()->byCode('shot')['id'], ModuleService::getInstance()->byCode('sequence')['id']])
            ->where("find_in_set({$entity['id']}, if(module_id = 47, get_json_string(`json`, '$.shot_level'),
                            get_json_string(`json`, '$.sequence_level'))) > 0")
            ->select();

        $res = [$entity];
        $sequenceList = [];
        foreach ($entityList as $entity) {
            $entityModule = ModuleService::getInstance()->byId($entity['module_id']);
            if ($entityModule['code'] === 'sequence') {
                $sequenceList[] = $entity;
            }
        }
        $res = array_merge($res, $entityList);

        if (!empty($sequenceList)) {
            $shotEntityList = $this->getSequenceListDownstreamEntities($sequenceList);
            if (!empty($shotEntityList)) {
                $res = array_merge($res, $shotEntityList);
            }
        }
        return $res;
    }

    /**
     * 查询序列下的镜头列表
     * @param array $sequenceList
     * @return EntityModel[]|array|\think\Collection|\think\db\Query[]|\think\model\Collection
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getSequenceListDownstreamEntities(array $sequenceList)
    {
        $sequenceIdList = array_column($sequenceList, 'id');
        return EntityModel::where("project_id", $sequenceList[0]['project_id'])->where("module_id", ModuleService::getInstance()->byCode('shot')['id'])->where("entity_id", "IN", $sequenceIdList)->select();
    }

    /**
     * 查询资产的下游实体列表
     * @param $entity
     * @return array
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getAssetDownstreamEntities($entity): array
    {
        $entityList = EntityModel::where("project_id", $entity['project_id'])
            ->where("module_id", "IN", [ModuleService::getInstance()->byCode('shot')['id'], ModuleService::getInstance()->byCode('sequence')['id']])
            ->where("find_in_set({$entity['id']}, if(module_id = 47, get_json_string(`json`, '$.shot_asset'),
      if(module_id=46,get_json_string(`json`, '$.sequence_asset'),get_json_string(`json`, '$.level_asset'))
      )) > 0")
            ->select();

        $res = [$entity];
        $sequenceList = [];
        $levelList = [];
        foreach ($entityList as $entity) {
            $entityModule = ModuleService::getInstance()->byId($entity['module_id']);
            if ($entityModule['code'] === 'sequence') {
                $sequenceList[] = $entity;
            } elseif ($entityModule['code'] === 'level') {
                $levelList[] = $entity;
            }
        }
        $res = array_merge($res, $entityList->toArray());

        if (!empty($sequenceList)) {
            $shotEntityList = $this->getSequenceListDownstreamEntities($sequenceList);
            if (!empty($shotEntityList)) {
                $res = array_merge($res, $shotEntityList->toArray());
            }
        }

        if (!empty($levelList)) {
            foreach ($levelList as $level) {
                $levelRelateEntityList = $this->getLevelDownstreamEntities($level);
                if (!empty($levelRelateEntityList)) {
                    $res = array_merge($res, $levelRelateEntityList);
                }
            }
        }

        return $res;
    }
}